#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include "soft_timer.h"

/* 定时器管理器 */
typedef struct
{
    /* 链表头指针，指向定时器链表头 */
    soft_timer_t *list_head;
    /* 定时器ticks */
    volatile soft_timer_base_t ticks;
} soft_timer_mgr_t;

/* 定时器管理参数 */
static soft_timer_mgr_t soft_timer_mgr;
pthread_t soft_timer_emu_thread;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
uint32_t is_running = 0;

void *timer_isr_emulator(void *arg)
{
    pthread_mutex_lock(&mutex);
    is_running = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    while(is_running) {
        soft_timer_inc_ticks();
        usleep(10);
    }
}


/* 初始化定时器管理器 */
void soft_timer_mgr_init(void)
{
    soft_timer_mgr.ticks = 0;
    soft_timer_mgr.list_head = NULL;
    pthread_condattr_t attr;
    pthread_mutex_init(&mutex, NULL);
    pthread_condattr_init(&attr);
    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    pthread_cond_init(&cond, &attr);
    pthread_condattr_destroy(&attr);
    pthread_create(&soft_timer_emu_thread, NULL, timer_isr_emulator, NULL);
    pthread_mutex_lock(&mutex);
    while(!is_running) {
        pthread_cond_wait(&cond, &mutex);
    }
    pthread_mutex_unlock(&mutex);
}

/* 初始化定时器管理器 */
void soft_timer_mgr_destroy(void)
{
    is_running = 0;
    pthread_join(soft_timer_emu_thread, NULL);
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);
}

/* 获取定时器头 */
soft_timer_t *soft_timer_get_list_head(void)
{
    return soft_timer_mgr.list_head;
}

/* 添加定时器进链表头部 */
static bool soft_timer_add_to_list_head(soft_timer_t* ptimer)
{
    soft_timer_t* ptemp = soft_timer_mgr.list_head;

    if (ptimer == NULL)
    {
        return false;
    }
    
    /* 搜索是否已经存在于链表中 */
    while (ptemp != NULL)
    {
        if (ptemp == ptimer)
        {
            /* 已存在 */
            return false;
        }
        ptemp = ptemp->next;
    }

    /* 添加到链表头部 */
    ptimer->next = soft_timer_mgr.list_head;
    soft_timer_mgr.list_head = ptimer;

    return true;
}

/* 初始化定时器，每个定时器使用前需要初始化一下 */
bool soft_timer_init(soft_timer_t *ptimer,
                   soft_timer_mode_t mode,
                   soft_timer_base_t times,
                   soft_timer_base_t interval_ms,
                   soft_timer_cb_t *cb)
{
    if (ptimer == NULL)
    {
        return false;
    }

    if ((interval_ms == 0) ||
        (interval_ms > SOFT_TIMER_MAX_INTERVAL))
    {
        return false;
    }

    ptimer->mode = mode;
    ptimer->times = times;
    ptimer->next = NULL;
    ptimer->interval = interval_ms;
    ptimer->status = SOFT_TIMER_STATUS_PENDING;
    ptimer->cb = cb;

    return soft_timer_add_to_list_head(ptimer);
}

/* 从链表移除定时器 */
bool soft_timer_remove(soft_timer_t *ptimer)
{
    soft_timer_t* ptemp = soft_timer_mgr.list_head;

    if ((ptimer == NULL) || (ptemp == NULL))
    {
        /* 定时器非法 */
        return false;
    }

    /* 判断是否是链表头节点 */
    if (ptemp == ptimer)
    {
        /* 头直接指向下一个 */
        soft_timer_mgr.list_head = soft_timer_mgr.list_head->next;
        /* 释放指针，防止别人摆弄 */
        ptimer->next = NULL;

        return true;
    }

    /* 搜索链表中timer位置的前一个 */
    while ((ptemp != NULL) && (ptemp->next != ptimer))
    {
        ptemp = ptemp->next;
    }

    if (ptemp == NULL)
    { 
        /* 定时器不在链表中 */
        return false;
    }

    /* 断链 */
    ptemp->next = ptimer->next;
    /* 释放指针，防止别人摆弄 */
    ptimer->next = NULL;

    return true;
}

/* 移除全部定时器 */
bool soft_timer_remove_all(void)
{
    soft_timer_t *ptemp = soft_timer_mgr.list_head;
    soft_timer_t *pnext = ptemp;

    while (ptemp != NULL)
    {
        /* 备份下一个 */
        pnext = ptemp->next;
        /* 释放指针，防止别人摆弄 */
        ptemp->next = NULL;
        /* 移到下一个 */
        ptemp = pnext;
    }

    /* 头节点为空 */
    soft_timer_mgr.list_head = NULL;

    return true;
}

/* 启动定时器 */
bool soft_timer_start(soft_timer_t *ptimer)
{
    if (ptimer == NULL)
    {
        /* 定时器非法 */
        return false;
    }
    /* 切换为运行态 */
    ptimer->status = SOFT_TIMER_STATUS_RUNNING;
    /* 保存当前ticks */
    ptimer->last = soft_timer_mgr.ticks;

    return true;
}

/* 停止定时器 */
bool soft_timer_stop(soft_timer_t *ptimer)
{
    if (ptimer == NULL)
    {
        /* 定时器非法 */
        return false;
    }
    /* 切换为挂起态 */
    ptimer->status = SOFT_TIMER_STATUS_PENDING;
    /* 保存当前ticks，用于仿真调试时查看停止时间 */
    ptimer->last = soft_timer_mgr.ticks;

    return true;
}

/* 轮询一个定时器 */
static void soft_timer_poll_timer(soft_timer_t *ptimer)
{
    soft_timer_base_t delta = soft_timer_mgr.ticks - ptimer->last;

    if (delta >= ptimer->interval)
    {
        switch (ptimer->mode)
        {
        case SOFT_TIMER_MODE_ONCE:
            ptimer->status = SOFT_TIMER_STATUS_PENDING;
            break;

        case SOFT_TIMER_MODE_MANY:
            if (--ptimer->times)
            {
                ptimer->last = ptimer->last + ptimer->interval;
            }
            else
            {
                ptimer->status = SOFT_TIMER_STATUS_PENDING;
            }
            break;

        case SOFT_TIMER_MODE_FOREVER:
            ptimer->last = ptimer->last + ptimer->interval;
            break;

        default:
            break;
        }

        if (ptimer->cb != NULL)
        {
            ptimer->cb(ptimer);
        }
    }
}

/* 定时器事件轮询处理 */
void soft_timer_poll_event(void)
{
    soft_timer_t* ptemp = soft_timer_mgr.list_head;
    
    for (; ptemp != NULL; ptemp = ptemp->next)
    {
        usleep(10);
        if (ptemp->status == SOFT_TIMER_STATUS_RUNNING)
        {
            soft_timer_poll_timer(ptemp);
        }
    }
}

/* 获取系统ticks总数 */
soft_timer_base_t soft_timer_get_ticks(void)
{
    return soft_timer_mgr.ticks;
}

/* 定时器ticks自增 */
void soft_timer_inc_ticks(void)
{
    struct timespec tm;
    clock_gettime(CLOCK_MONOTONIC, &tm);
    /* update ticks ms */
    soft_timer_mgr.ticks = tm.tv_sec * 1000 + tm.tv_nsec / 1000000;
}
